#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXSIZE 100 // 顺序表可能达到的最大长度

typedef int Status; // Status 是函数返回值类型，其值是函数结果状态代码。
// typedef int ElemType; //ElemType 为可定义的数据类型，此设为int类型
struct Book {
	string id;	  // ISBN
	string name;  // 书名
	double price; // 定价
};
typedef struct Book ElemType; // ElemType 为可定义的数据类型，此设为int类型

typedef struct {
	ElemType *elem=NULL; // 存储空间的基地址
	int length=0;		// 当前长度
} SqList;

SqList L;

// 算法2.1 顺序表的初始化
Status InitList(SqList &L) {
	// 构造一个空的顺序表L
	L.elem = new ElemType[MAXSIZE]; // 为顺序表分配一个大小为MAXSIZE的数组空间
	if (!L.elem)
		exit(OVERFLOW); // 存储分配失败退出
	L.length = 0;		// 空表长度为0
	return OK;
}

// 销毁线性表L
Status DestroyList(SqList &L) {
	if (L.elem) {
		delete[] L.elem;
		L.elem = NULL;
	}
	L.length = 0;
	return OK;
}

// 清空线性表L
Status ClearList(SqList &L) {
	L.length = 0;
	return OK;
}


// 求线性表L的长度
int getListLength(SqList L) {
	return (L.length);
}

// 判断线性表L是否为空
int IsEmpty(SqList L) {
	if (L.length == 0)
		return 1;
	else
		return 0;
}

// 算法2.2　顺序表的取值
Status GetElem(SqList L, int i, ElemType &e) {
	if (i < 1 || i > L.length)
		return ERROR;  // 判断i值是否合理，若不合理，返回ERROR
	e = L.elem[i - 1]; // elem[i-1]单元存储第i个数据元素
	return OK;
}


// 算法2.3 顺序表的查找
int LocateElem(SqList L, double e) {
	// 顺序表的查找
	for (int i = 0; i < L.length; i++)
		if (L.elem[i].price == e)
			return i + 1; // 查找成功，返回序号i+1
	return 0;			  // 查找失败，返回0
}

// 算法2.4 顺序表的插入
Status ListInsert(SqList &L, int i, ElemType e) {
	// 在顺序表L中第i个位置之前插入新的元素e
	// i值的合法范围是1<=i<=L.length+1
	if ((i < 1) || (i > L.length + 1))
		return ERROR; // i值不合法
	if (L.length == MAXSIZE)
		return ERROR; // 当前存储空间已满
	for (int j = L.length - 1; j >= i - 1; j--)
		L.elem[j + 1] = L.elem[j]; // 插入位置及之后的元素后移
	L.elem[i - 1] = e;			   // 将新元素e放入第i个位置
	++L.length;					   // 表长增1
	return OK;
}

// 算法2.5 顺序表的删除
Status ListDelete(SqList &L, int i) {
	// 在顺序表L中删除第i个元素，并用e返回其值
	// i值的合法范围是1<=i<=L.length
	if ((i < 1) || (i > L.length))
		return ERROR; // i值不合法
	for (int j = i; j <= L.length; j++)
		L.elem[j - 1] = L.elem[j]; // 被删除元素之后的元素前移
	--L.length;					   // 表长减1
	return OK;
}
// 顺序表的输出
Status PrintList(SqList L) {
	cout << "当前顺序表信息输出:\n";
	for (int i = 0; i < L.length; i++) {
		cout << left << setw(15) << L.elem[i].id << "\t"
		     << left << setw(50) << L.elem[i].name << "\t"
		     << left << setw(5) << L.elem[i].price << endl;
	}
	cout << endl;
	return OK;
}

/////////////////////////////////////////////////////////////////////////////////
void testInitList() {
	cout << "测试初始化顺序表:\n";
	if (InitList(L))
		cout << "成功建立顺序表\n\n";
	else
		cout << "顺序表建立失败\n\n";
}

void testInputFromFile() {
	cout << "测试从文件输入数据:\n";
	if (InitList(L)) {
		cout << "成功建立顺序表\n";
	} else {
		cout << "顺序表建立失败\n";
		return;
	}
	fstream file;
	file.open("book.txt");
	if (!file) {
		cout << "错误！未找到文件！" << endl;
		exit(ERROR);
	}
	int i = 0;
	string head_1, head_2, head_3;
	file >> head_1 >> head_2 >> head_3;
	while (!file.eof()) {
		file >> L.elem[i].id >> L.elem[i].name >> L.elem[i].price;
		i++;
	}
	cout << "输入 book.txt 信息完毕\n";
	L.length = i;
	file.close();
	cout << endl;
}

void testGetElem() {
	cout << "测试取值操作:\n";
	int i;
	ElemType e;
	cout << "请输入一个位置用来取值：\n";
	cin >> i;
	int temp = GetElem(L, i, e);
	if (temp != 0) {
		cout << "查找成功\n";
		cout << "第" << i << "本图书的信息是：\n";
		cout << left << setw(15) << e.id << "\t" << left << setw(50)
		     << e.name << "\t" << left << setw(5) << e.price << endl;
	} else
		cout << "查找失败！位置超出范围\n";
	cout << endl;
}

void testLocateElem() {
	cout << "测试查找操作:\n";
	double price;
	cout << "请输入所要查找价格:";
	cin >> price;
	int temp = LocateElem(L, price);
	if (temp != 0) {
		cout << "查找成功\n";
		cout << "该价格对应的书名为：" << L.elem[temp - 1].name << endl;
	} else
		cout << "查找失败！没有这个价格对应的书籍\n";
	cout << endl;
}

void testListInsert() {
	cout << "测试插入操作:\n";
	int a;
	ElemType e;
	cout << "请输入插入的位置和书本信息，包括：编号 书名 价格（用空格隔开）:";
	cin >> a;
	cin >> e.id >> e.name >> e.price;
	if (ListInsert(L, a, e))
		cout << "插入成功.\n";
	else
		cout << "插入失败.\n";
	cout << endl;
}

void testListDelete() {
	cout << "测试删除操作:\n";
	int c;
	cout << "请输入所要删除的书籍的位置:";
	cin >> c;
	if (ListDelete(L, c))
		cout << "删除成功.\n";
	else
		cout << "删除失败.\n";
	cout << endl;
}

void testPrintList() {
	cout << "测试输出操作:\n";
	PrintList(L);
}

void testDestroyList() {
	cout << "测试销毁顺序表:\n";
	if (DestroyList(L))
		cout << "成功销毁顺序表\n";
	else
		cout << "销毁顺序表失败\n";
	cout << endl;
}

void testClearList() {
	cout << "测试清空顺序表:\n";
	if (ClearList(L))
		cout << "成功清空顺序表\n";
	else
		cout << "清空顺序表失败\n";
	cout << endl;
}

void testListEmpty() {
	cout << "测试顺序表是否为空:\n";
	if (IsEmpty(L))
		cout << "顺序表为空\n";
	else
		cout << "顺序表不为空\n";
	cout << endl;
}

void testListLength() {
	cout << "测试获取顺序表长度:\n";
	cout << "顺序表长度为: " << getListLength(L) << endl;
	cout << endl;
}

int main() {
	int choose = -1;
	while (choose != 0) {
		cout << "1. 初始化顺序表\n";
		cout << "2. 从文件输入数据\n";
		cout << "3. 取值\n";
		cout << "4. 查找\n";
		cout << "5. 插入\n";
		cout << "6. 删除\n";
		cout << "7. 输出\n";
		cout << "8. 销毁顺序表\n";
		cout << "9. 清空顺序表\n";
		cout << "10. 判断顺序表是否为空\n";
		cout << "11. 获取顺序表长度\n";
		cout << "0. 退出\n\n";
		cout << "请选择:";
		cin >> choose;
		switch (choose) {
			case 1:
				testInitList();
				break;
			case 2:
				testInputFromFile();
				break;
			case 3:
				testGetElem();
				break;
			case 4:
				testLocateElem();
				break;
			case 5:
				testListInsert();
				break;
			case 6:
				testListDelete();
				break;
			case 7:
				testPrintList();
				break;
			case 8:
				testDestroyList();
				break;
			case 9:
				testClearList();
				break;
			case 10:
				testListEmpty();
				break;
			case 11:
				testListLength();
				break;
		}
	}
	return 0;
}
